home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / awksrc.zip / ALLOCA.S < prev    next >
Text File  |  1991-04-26  |  11KB  |  353 lines

  1. /* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
  2.    Also has _setjmp and _longjmp for pyramids.
  3.    Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Emacs.
  6.  
  7. GNU Emacs is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Emacs General Public
  12. License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. GNU Emacs, but only under the conditions described in the
  16. GNU Emacs General Public License.   A copy of this license is
  17. supposed to have been given to you along with GNU Emacs so you
  18. can know your rights and responsibilities.  It should be in a
  19. file named COPYING.  Among other things, the copyright notice
  20. and this notice must be preserved on all copies.  */
  21.  
  22.  
  23. /* Both 68000 systems I have run this on have had broken versions of alloca.
  24.    Also, I am told that non-berkeley systems do not have it at all.
  25.    So replace whatever system-provided alloca there may be
  26.    on all 68000 systems.  */
  27.  
  28. #define NOT_C_CODE
  29. /* #include "config.h" */
  30.  
  31. #ifndef HAVE_ALLOCA  /* define this to use system's alloca */
  32.  
  33. #ifndef hp9000s300
  34. #ifndef m68k
  35. #ifndef mc68k
  36. #ifndef m68000
  37. #ifndef WICAT
  38. #ifndef ns32000
  39. #ifndef ns16000
  40. #ifndef sequent
  41. #ifndef pyramid
  42. #ifndef ATT3B5
  43. #ifndef XENIX
  44. you
  45. lose!!
  46. #endif /* XENIX */
  47. #endif /* ATT3B5 */
  48. #endif /* pyramid */
  49. #endif /* sequent */
  50. #endif /* ns16000 */
  51. #endif /* ns32000 */
  52. #endif /* WICAT */
  53. #endif /* m68000 */
  54. #endif /* mc68k */
  55. #endif /* m68k */
  56. #endif /* hp9000s300 */
  57.  
  58.  
  59. #ifdef hp9000s300
  60. #ifdef OLD_HP_ASSEMBLER
  61.     data
  62.     text
  63.     globl    _alloca
  64. _alloca    
  65.     move.l    (sp)+,a0    ; pop return addr from top of stack
  66.     move.l    (sp)+,d0    ; pop size in bytes from top of stack
  67.     add.l    #ROUND,d0    ; round size up to long word
  68.     and.l    #MASK,d0    ; mask out lower two bits of size
  69.     sub.l    d0,sp        ; allocate by moving stack pointer
  70.     tst.b    PROBE(sp)    ; stack probe to allocate pages
  71.     move.l    sp,d0        ; return pointer
  72.     add.l    #-4,sp        ; new top of stack
  73.     jmp    (a0)        ; not a normal return
  74. MASK    equ    -4        ; Longword alignment
  75. ROUND    equ    3        ; ditto
  76. PROBE    equ    -128        ; safety buffer for C compiler scratch
  77.     data
  78. #else /* new hp assembler syntax */
  79. /*
  80.   The new compiler does "move.m <registers> (%sp)" to save registers,
  81.     so we must copy the saved registers when we mung the sp.
  82.   The old compiler did "move.m <register> <offset>(%a6)", which
  83.     gave us no trouble
  84.  */
  85.     text
  86.     set    PROBE,-128    # safety for C frame temporaries
  87.     set    MAXREG,22    # d2-d7, a2-a5, fp2-fp7 may have been saved
  88.     global    _alloca
  89. _alloca:
  90.     mov.l    (%sp)+,%a0    # return addess
  91.     mov.l    (%sp)+,%d0    # number of bytes to allocate
  92.     mov.l    %sp,%a1        # save old sp for register copy
  93.     mov.l    %sp,%d1        # compute new sp
  94.     sub.l    %d0,%d1        # space requested
  95.     and.l    &-4,%d1        # round down to longword
  96.     sub.l    &MAXREG*4,%d1    # space for saving registers
  97.     mov.l    %d1,%sp        # save new value of sp
  98.     tst.b    PROBE(%sp)    # create pages (sigh)
  99.     mov.l    %a2,%d1        # save reg a2
  100.     mov.l    %sp,%a2
  101.     move.w    &MAXREG-1,%d0
  102. copy_regs_loop:            /* save caller's saved registers */
  103.     mov.l    (%a1)+,(%a2)+
  104.     dbra    %d0,copy_regs_loop
  105.     mov.l    %a2,%d0        # return value
  106.     mov.l    %d1,%a2        # restore a2
  107.     add.l    &-4,%sp        # adjust tos
  108.     jmp    (%a0)        # rts
  109. #endif /* new hp assembler */
  110. #else
  111. #if defined(m68k) || defined(mc68k)    /* SGS assembler totally different */
  112.     file    "alloca.s"
  113.     global    alloca
  114. alloca:
  115. #ifdef MOTOROLA_DELTA
  116. /* slightly modified version of alloca to motorola sysV/68 pcc - based
  117.    compiler. 
  118.    this compiler saves used regfisters relative to %sp instead of %fp.
  119.    alright, just make new copy of saved register set whenever we allocate
  120.    new space from stack..
  121.    this is true at last until SVR3V5.1 . bug has reported to Motorola. */
  122.     set    MAXREG,10    # max no of registers to save (d2-d7, a2-a5)
  123.         mov.l   (%sp)+,%a1    # pop return addr from top of stack
  124.         mov.l   (%sp)+,%d0    # pop size in bytes from top of stack
  125.     mov.l    %sp,%a0        # save stack pointer for register copy
  126.         addq.l  &3,%d0        # round size up to long word
  127.         andi.l  &-4,%d0        # mask out lower two bits of size
  128.     mov.l    %sp,%d1        # compute new value of sp to d1
  129.         sub.l    %d0,%d1        # pseudo-allocate by moving stack pointer
  130.     sub.l    &MAXREG*4,%d1    # allocate more space for saved regs.
  131.     mov.l    %d1,%sp        # actual alloaction.
  132.     move.w    &MAXREG-1,%d0    # d0 counts saved regs.
  133.     mov.l    %a2,%d1        # preserve a2.
  134.     mov.l    %sp,%a2        # make pointer to new reg save area.
  135. copy_regs_loop:         # copy stuff from old save area.
  136.     mov.l    (%a0)+,(%a2)+    # save saved register
  137.     dbra    %d0,copy_regs_loop
  138.         mov.l   %a2,%a0        # now a2 is start of allocated space.
  139.     mov.l    %a2,%d0        # return it in both a0 and d0 to play safe.
  140.     mov.l    %d1,%a2        # restore a2.
  141.         subq.l  &4,%sp        # new top of stack
  142.         jmp     (%a1)        # far below normal return
  143. #else /* not MOTOROLA_DELTA */
  144.     mov.l    (%sp)+,%a1    # pop return addr from top of stack
  145.     mov.l    (%sp)+,%d0    # pop size in bytes from top of stack
  146.     add.l    &R%1,%d0    # round size up to long word
  147.     and.l    &-4,%d0        # mask out lower two bits of size
  148.     sub.l    %d0,%sp        # allocate by moving stack pointer
  149.     tst.b    P%1(%sp)    # stack probe to allocate pages
  150.     mov.l    %sp,%a0        # return pointer as pointer
  151.     mov.l    %sp,%d0        # return pointer as int to avoid disaster
  152.     add.l    &-4,%sp        # new top of stack
  153.     jmp    (%a1)        # not a normal return
  154.     set    S%1,64        # safety factor for C compiler scratch
  155.     set    R%1,3+S%1    # add to size for rounding
  156.     set    P%1,-132    # probe this far below current top of stack
  157. #endif /* not MOTOROLA_DELTA */
  158.  
  159. #else /* not m68k && not mc68k */
  160.  
  161. #ifdef m68000
  162.  
  163. #ifdef WICAT
  164. /*
  165.  * Registers are saved after the corresponding link so we have to explicitly
  166.  * move them to the top of the stack where they are expected to be.
  167.  * Since we do not know how many registers were saved in the calling function
  168.  * we must assume the maximum possible (d2-d7,a2-a5).  Hence, we end up
  169.  * wasting some space on the stack.
  170.  *
  171.  * The large probe (tst.b) attempts to make up for the fact that we have
  172.  * potentially used up the space that the caller probed for its own needs.
  173.  */
  174.     .procss m0
  175.     .config "68000 1"
  176.     .module    _alloca
  177. MAXREG:    .const    10
  178.     .sect    text
  179.     .global    _alloca
  180. _alloca:
  181.     move.l    (sp)+,a1    ; pop return address
  182.     move.l    (sp)+,d0    ; pop allocation size
  183.     move.l    sp,d1        ; get current SP value
  184.     sub.l    d0,d1        ; adjust to reflect required size...
  185.     sub.l    #MAXREG*4,d1    ; ...and space needed for registers
  186.     and.l    #-4,d1        ; backup to longword boundry
  187.     move.l    sp,a0        ; save old SP value for register copy
  188.     move.l    d1,sp        ; set the new SP value
  189.     tst.b    -4096(sp)    ; grab an extra page (to cover caller)
  190.     move.l    a2,d1        ; save callers register
  191.     move.l    sp,a2
  192.     move.w    #MAXREG-1,d0    ; # of longwords to copy
  193. loop:    move.l    (a0)+,(a2)+    ; copy registers...
  194.     dbra    d0,loop        ; ...til there are no more
  195.     move.l    a2,d0        ; end of register area is addr for new space
  196.     move.l    d1,a2        ; restore saved a2.
  197.     addq.l    #4,sp        ; caller will increment sp by 4 after return.
  198.     move.l    d0,a0        ; return value in both a0 and d0.
  199.     jmp    (a1)
  200.     .end    _alloca
  201. #else
  202.  
  203. /* Some systems want the _, some do not.  Win with both kinds.  */
  204. .globl    _alloca
  205. _alloca:
  206. .globl    alloca
  207. alloca:
  208.     movl    sp@+,a0
  209.     movl    a7,d0
  210.     subl    sp@,d0
  211.     andl    #~3,d0
  212.     movl    d0,sp
  213.     tstb    sp@(0)        /* Make stack pages exist  */
  214.                 /* Needed on certain systems
  215.                    that lack true demand paging */
  216.     addql    #4,d0
  217.     jmp    a0@
  218.  
  219. #endif /* not WICAT */
  220. #endif /* m68000 */
  221. #endif /* not m68k */
  222. #endif /* not hp9000s300 */
  223.  
  224. #if defined (ns16000) || defined (ns32000)
  225.  
  226.     .text
  227.     .align    2
  228. /* Some systems want the _, some do not.  Win with both kinds.  */
  229. .globl    _alloca
  230. _alloca:
  231. .globl    alloca
  232. alloca:
  233.  
  234. /* Two different assembler syntaxes are used for the same code
  235.     on different systems.  */
  236.  
  237. #ifdef sequent
  238. #define IM
  239. #define REGISTER(x) x
  240. #else
  241. #ifdef NS5   /* ns SysV assembler */
  242. #define IM $
  243. #define REGISTER(x) x
  244. #else
  245. #define IM $
  246. #define REGISTER(x) 0(x)
  247. #endif
  248. #endif
  249.  
  250. /*
  251.  * The ns16000 is a little more difficult, need to copy regs.
  252.  * Also the code assumes direct linkage call sequence (no mod table crap).
  253.  * We have to copy registers, and therefore waste 32 bytes.
  254.  *
  255.  * Stack layout:
  256.  * new    sp ->    junk    
  257.  *         registers (copy)
  258.  *    r0 ->    new data        
  259.  *         |       (orig retval)
  260.  *         |      (orig arg)
  261.  * old  sp ->    regs      (orig)
  262.  *        local data
  263.  *    fp ->    old fp
  264.  */
  265.  
  266.     movd    tos,r1        /*  pop return addr */
  267.     negd    tos,r0        /*  pop amount to allocate */
  268.     sprd    sp,r2
  269.     addd    r2,r0
  270.     bicb    IM/**/3,r0    /*  4-byte align */
  271.     lprd    sp,r0
  272.     adjspb    IM/**/36    /*  space for regs, +4 for caller to pop */
  273.     movmd    0(r2),4(sp),IM/**/4    /*  copy regs */
  274.     movmd    0x10(r2),0x14(sp),IM/**/4
  275.     jump    REGISTER(r1)    /* funky return */
  276. #endif /* ns16000 or ns32000 */
  277.  
  278. #ifdef pyramid
  279.  
  280. .globl _alloca
  281.  
  282. _alloca: addw $3,pr0    # add 3 (dec) to first argument
  283.     bicw $3,pr0    # then clear its last 2 bits
  284.     subw pr0,sp    # subtract from SP the val in PR0
  285.     andw $-32,sp    # keep sp aligned on multiple of 32.
  286.     movw sp,pr0    # ret. current SP
  287.     ret
  288.  
  289. #ifdef PYRAMID_OLD /* This isn't needed in system version 4.  */
  290. .globl __longjmp
  291. .globl _longjmp
  292. .globl __setjmp
  293. .globl _setjmp
  294.  
  295. __longjmp: jump _longjmp
  296. __setjmp:  jump _setjmp
  297. #endif
  298.  
  299. #endif /* pyramid */
  300.  
  301. #ifdef ATT3B5
  302.  
  303.     .align 4
  304.     .globl alloca
  305.  
  306. alloca:
  307.     movw %ap, %r8
  308.     subw2 $9*4, %r8
  309.     movw 0(%r8), %r1    /* pc */
  310.     movw 4(%r8), %fp
  311.     movw 8(%r8), %sp
  312.     addw2 %r0, %sp /* make room */
  313.     movw %sp, %r0 /* return value */
  314.     jmp (%r1) /* continue... */
  315.  
  316. #endif /* ATT3B5 */
  317.  
  318. #ifdef XENIX
  319.  
  320. .386
  321.  
  322. _TEXT segment dword use32 public 'CODE'
  323. assume   cs:_TEXT
  324.  
  325. ;-------------------------------------------------------------------------
  326.  
  327. public _alloca
  328. _alloca proc near
  329.  
  330.     pop    ecx        ; return address
  331.     pop    eax        ; amount to alloc
  332.     add    eax,3        ; round it to 32-bit boundary
  333.     and    al,11111100B    ;
  334.     mov    edx,esp        ; current sp in edx
  335.     sub    edx,eax        ; lower the stack
  336.     xchg    esp,edx        ; start of allocation in esp, old sp in edx
  337.     mov    eax,esp        ; return ptr to base in eax
  338.     push    [edx+8]        ; save poss. stored reg. values (esi,edi,ebx)
  339.     push    [edx+4]        ;  on lowered stack
  340.     push    [edx]        ;
  341.     sub    esp,4        ; allow for 'add esp, 4'
  342.     jmp    ecx        ; jump to return address
  343.  
  344. _alloca endp
  345.  
  346. _TEXT    ends
  347.  
  348. end
  349.  
  350. #endif /* XENIX */
  351.  
  352. #endif /* not HAVE_ALLOCA */
  353.